package com.mornd.shiro;

import com.mornd.entity.LoginUser;
import com.mornd.entity.Menu;
import com.mornd.entity.Role;
import com.mornd.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author mornd
 * @date 2020/12/28 - 20:17
 * 自定义的UserRealm
 */
public class UserRealm extends AuthorizingRealm {
    @Lazy
    @Resource
    private UserService userService;

    /**
     * 授权方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        principalCollection.getPrimaryPrincipal();
        //拿到当前登录的用户信息
        //LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LoginUser currentUser = (LoginUser) principalCollection.getPrimaryPrincipal();
        //创建shiro授权对象
        SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();
        //遍历角色与权限
        Set<Role> roleSet = currentUser.getRoleSet();
        if(!ObjectUtils.isEmpty(roleSet)){
            roleSet.forEach(role -> {
                //添加角色
                authorization.addRole(role.getCode());
                Set<Menu> menuSet = role.getMenuSet();
                if(!ObjectUtils.isEmpty(menuSet)){
                    List<String> menus = menuSet.stream().map(Menu::getCode).collect(Collectors.toList());
                    //添加权限
                    authorization.addStringPermissions(menus);
                }
            });
        }
        return authorization;
    }

    /**
     * 身份认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //String username = (String) authenticationToken.getPrincipal();//获取用户名
        //token中取出用户名密码
        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        if(ObjectUtils.isEmpty(userToken)) return null;
        LoginUser loginUser = userService.findUserByAccount(userToken.getUsername());
        //用户名不存在
        if(ObjectUtils.isEmpty(loginUser)){
            return null;//返回null 则自动抛出异常 UnknownAccountException
        }
        //账号禁用
        if(loginUser.getStatus() == 0){
            throw new DisabledAccountException();
        }
        //加密盐值
        ByteSource salt = ByteSource.Util.bytes(loginUser.getSalt());
        return new SimpleAuthenticationInfo(loginUser,loginUser.getPassword(),salt,super.getName());
    }
}
